Xotirani samarali boshqarish uchun JavaScript WeakMap va WeakSet'ni o'rganing. Bu to'plamlar murakkab ilovalarda ishlash unumdorligini oshirib, foydalanilmayotgan xotirani qanday avtomatik tarzda bo'shatishini bilib oling.
JavaScript WeakMap va WeakSet: Xotirani Samarali Boshqaruvchi To'plamlarni O'zlashtirish
JavaScript ma'lumotlar to'plamlarini boshqarish uchun bir nechta o'rnatilgan ma'lumotlar tuzilmalarini taklif qiladi. Standart Map va Set kuchli vositalarni taqdim etsa-da, ular ba'zan, ayniqsa murakkab ilovalarda, xotira sizib chiqishiga olib kelishi mumkin. Aynan shu yerda WeakMap va WeakSet yordamga keladi. Ushbu ixtisoslashtirilgan to'plamlar xotirani boshqarishga noyob yondashuvni taklif qilib, JavaScript'ning axlat yig'uvchisiga xotirani samaraliroq qayta ishlashga imkon beradi.
Muammoni Tushunish: Kuchli Havolalar
WeakMap va WeakSetni ko'rib chiqishdan oldin, asosiy muammoni tushunib olaylik: kuchli havolalar. JavaScript'da obyekt Mapda kalit yoki Setda qiymat sifatida saqlanganda, to'plam ushbu obyektga kuchli havola saqlaydi. Bu shuni anglatadiki, Map yoki Set mavjud ekan, axlat yig'uvchi obyekt egallagan xotirani, hatto kodning boshqa hech bir joyida ushbu obyektga havola qilinmasa ham, qayta ishlay olmaydi. Bu, ayniqsa, katta yoki uzoq muddatli to'plamlar bilan ishlaganda, xotira sizib chiqishiga olib kelishi mumkin.
Ushbu misolni ko'rib chiqing:
let myMap = new Map();
let key = { id: 1, name: "Example Object" };
myMap.set(key, "Some value");
// 'key' endi to'g'ridan-to'g'ri ishlatilmasa ham...
key = null;
// ... Map hali ham unga havolani saqlab turadi.
console.log(myMap.size); // Natija: 1
Ushbu stsenariyda, key o'zgaruvchisiga null qiymatini berganimizdan keyin ham, Map asl obyektga havolani saqlab turadi. Axlat yig'uvchi ushbu obyekt tomonidan ishlatilgan xotirani qayta ishlay olmaydi, chunki Map bunga to'sqinlik qiladi.
WeakMap va WeakSet bilan tanishuv: Yordamga Keluvchi Kuchsiz Havolalar
WeakMap va WeakSet bu muammoni kuchsiz havolalardan foydalanib hal qiladi. Kuchsiz havola, agar obyektga boshqa kuchli havolalar bo'lmasa, uni axlat yig'uvchi tomonidan tozalanishiga imkon beradi. WeakMapdagi kalit yoki WeakSetdagi qiymatga faqat kuchsiz havola qilinganida, axlat yig'uvchi xotirani qayta ishlashda erkin bo'ladi. Obyekt axlat yig'uvchi tomonidan tozalangandan so'ng, tegishli yozuv avtomatik ravishda WeakMap yoki WeakSetdan o'chiriladi.
WeakMap: Kuchsiz Kalitlarga Ega Kalit-Qiymat Juftliklari
WeakMap - bu kalit-qiymat juftliklari to'plami bo'lib, unda kalitlar obyekt bo'lishi shart. Kalitlar kuchsiz saqlanadi, ya'ni agar kalit obyektiga boshqa joyda havola qilinmasa, u axlat yig'uvchi tomonidan tozalanishi mumkin va WeakMapdagi tegishli yozuv o'chiriladi. Boshqa tomondan, qiymatlar oddiy (kuchli) havolalar bilan saqlanadi.
Mana bir oddiy misol:
let weakMap = new WeakMap();
let key = { id: 1, name: "WeakMap Key" };
let value = "Associated Data";
weakMap.set(key, value);
console.log(weakMap.get(key)); // Natija: "Associated Data"
key = null;
// Axlat yig'ilgandan so'ng (bu darhol sodir bo'lishi kafolatlanmagan)...
// weakMap.get(key) 'undefined' qaytarishi mumkin. Bu implementatsiyaga bog'liq.
// WeakMap'dan yozuv qachon o'chirilganini to'g'ridan-to'g'ri kuzata olmaymiz, bu ataylab shunday qilingan.
Map'dan Asosiy Farqlari:
- Kalitlar obyekt bo'lishi kerak:
WeakMapda kalit sifatida faqat obyektlar ishlatilishi mumkin. Primitiv qiymatlar (string, number, boolean, symbol) ruxsat etilmaydi. Buning sababi, primitiv qiymatlar o'zgarmasdir va obyektlar kabi axlat yig'ishni talab qilmaydi. - Iteratsiya yo'q:
WeakMapning kalitlari, qiymatlari yoki yozuvlari ustida iteratsiya qila olmaysiz.forEach,keys(),values()yokientries()kabi metodlar mavjud emas. Buning sababi, bu metodlarning mavjudligiWeakMapdan o'z kalitlariga kuchli havola saqlashni talab qilgan bo'lar edi, bu esa kuchsiz havolalarning maqsadiga zid keladi. - size xususiyati yo'q:
WeakMapdasizexususiyati yo'q. Hajmini aniqlash ham kalitlar ustida iteratsiya qilishni talab qiladi, bu esa mumkin emas. - Cheklangan Metodlar:
WeakMapfaqatget(key),set(key, value),has(key)vadelete(key)metodlarini taklif qiladi.
WeakSet: Kuchsiz Saqlanadigan Obyektlar To'plami
WeakSet Setga o'xshaydi, lekin u faqat obyektlarni qiymat sifatida saqlashga imkon beradi. WeakMap kabi, WeakSet ham bu obyektlarni kuchsiz saqlaydi. Agar WeakSetdagi obyektga boshqa joyda kuchli havola qilinmasa, u axlat yig'uvchi tomonidan tozalanishi mumkin va WeakSet avtomatik ravishda obyektni o'chiradi.
Mana bir oddiy misol:
let weakSet = new WeakSet();
let obj1 = { id: 1, name: "Object 1" };
let obj2 = { id: 2, name: "Object 2" };
weakSet.add(obj1);
weakSet.add(obj2);
console.log(weakSet.has(obj1)); // Natija: true
obj1 = null;
// Axlat yig'ilgandan so'ng (darhol sodir bo'lishi kafolatlanmagan)...
// weakSet.has(obj1) 'false' qaytarishi mumkin. Bu implementatsiyaga bog'liq.
// WeakSet'dan element qachon olib tashlanganini to'g'ridan-to'g'ri kuzata olmaymiz.
Set'dan Asosiy Farqlari:
- Qiymatlar obyekt bo'lishi kerak:
WeakSetda faqat obyektlar saqlanishi mumkin. Primitiv qiymatlarga ruxsat berilmaydi. - Iteratsiya yo'q: Siz
WeakSetustida iteratsiya qila olmaysiz.forEachmetodi yoki elementlarga kirishning boshqa usullari mavjud emas. - size xususiyati yo'q:
WeakSetdasizexususiyati yo'q. - Cheklangan Metodlar:
WeakSetfaqatadd(value),has(value)vadelete(value)metodlarini taklif qiladi.
WeakMap va WeakSet uchun Amaliy Foydalanish Holatlari
WeakMap va WeakSetning cheklovlari ularni o'zlarining kuchliroq analoglariga qaraganda kamroq moslashuvchan ko'rsatishi mumkin. Biroq, ularning noyob xotirani boshqarish imkoniyatlari ularni ma'lum stsenariylarda beqiyos qiladi.
1. DOM Elementi Metama'lumotlari
Keng tarqalgan foydalanish holatlaridan biri bu DOM elementlariga metama'lumotlarni DOMni ifloslantirmasdan bog'lashdir. Masalan, siz ma'lum bir HTML elementi bilan bog'liq komponentga xos ma'lumotlarni saqlashni xohlashingiz mumkin. WeakMap yordamida, DOM elementi sahifadan olib tashlanganda, u bilan bog'liq metama'lumotlar ham axlat yig'uvchi tomonidan tozalanishini ta'minlab, xotira sizib chiqishining oldini olishingiz mumkin.
let elementData = new WeakMap();
function initializeComponent(element) {
let componentData = {
// Komponentga xos ma'lumotlar
isActive: false,
onClick: () => { console.log("Bosildi!"); }
};
elementData.set(element, componentData);
}
let myElement = document.getElementById("myElement");
initializeComponent(myElement);
// Keyinroq, element DOMdan olib tashlanganda:
// myElement.remove();
// myElement bilan bog'liq bo'lgan componentData oxir-oqibat axlat yig'uvchi tomonidan tozalanadi
// agar myElement'ga boshqa kuchli havolalar bo'lmasa.
Ushbu misolda elementData DOM elementlari bilan bog'liq metama'lumotlarni saqlaydi. myElement DOMdan olib tashlanganda, axlat yig'uvchi uning xotirasini qayta ishlashi mumkin va elementDatadagi tegishli yozuv avtomatik ravishda o'chiriladi.
2. Qimmat Operatsiyalar Natijalarini Keshlashtirish
Siz WeakMapdan qimmat operatsiyalarning natijalarini kirish obyektlariga asoslanib keshlashtirish uchun foydalanishingiz mumkin. Agar kirish obyekti endi ishlatilmasa, keshlashtirilgan natija avtomatik ravishda WeakMapdan o'chiriladi va xotira bo'shatiladi.
let cache = new WeakMap();
function expensiveOperation(input) {
if (cache.has(input)) {
console.log("Keshdan olindi!");
return cache.get(input);
}
console.log("Keshda topilmadi!");
// Qimmat operatsiyani bajarish
let result = input.id * 100;
cache.set(input, result);
return result;
}
let obj1 = { id: 5 };
let obj2 = { id: 10 };
console.log(expensiveOperation(obj1)); // Natija: Keshda topilmadi!, 500
console.log(expensiveOperation(obj1)); // Natija: Keshdan olindi!, 500
console.log(expensiveOperation(obj2)); // Natija: Keshda topilmadi!, 1000
obj1 = null;
// Axlat yig'ilgandan so'ng, obj1 uchun yozuv keshdan o'chiriladi.
3. Obyektlar uchun Maxfiy Ma'lumotlar (Maxfiy Maydonlar Sifatida WeakMap)
JavaScript'da maxfiy sinf maydonlari joriy etilishidan oldin, WeakMap obyektlar ichida maxfiy ma'lumotlarni simulyatsiya qilishning keng tarqalgan usuli edi. Har bir obyekt WeakMapda saqlanadigan o'zining maxfiy ma'lumotlari bilan bog'lanardi. Ma'lumotlarga faqat WeakMap va obyektning o'zi orqali kirish mumkin bo'lganligi sababli, u samarali tarzda maxfiy hisoblanadi.
let _privateData = new WeakMap();
class MyClass {
constructor(secret) {
_privateData.set(this, { secret: secret });
}
getSecret() {
return _privateData.get(this).secret;
}
}
let instance = new MyClass("Mening Maxfiy Qiymatim");
console.log(instance.getSecret()); // Natija: Mening Maxfiy Qiymatim
// _privateData'ga to'g'ridan-to'g'ri kirishga urinish ish bermaydi.
// console.log(_privateData.get(instance).secret); // Xatolik (_privateData'ga qandaydir yo'l bilan kira olgan bo'lsangiz)
// Agar instansiya axlat yig'uvchi tomonidan tozalansa ham, _privateData'dagi tegishli yozuv o'chiriladi.
Hozirda maxfiy sinf maydonlari afzalroq yondashuv bo'lsa-da, ushbu WeakMap usulini tushunish eski kod va JavaScript tarixini tushunish uchun hali ham qimmatlidir.
4. Obyektning Hayot Siklini Kuzatish
WeakSet obyektlarning hayot siklini kuzatish uchun ishlatilishi mumkin. Obyektlarni yaratilganda WeakSetga qo'shishingiz va keyin ularning WeakSetda hali ham mavjudligini tekshirishingiz mumkin. Obyekt axlat yig'uvchi tomonidan tozalanganda, u avtomatik ravishda WeakSetdan o'chiriladi.
let trackedObjects = new WeakSet();
function trackObject(obj) {
trackedObjects.add(obj);
}
function isObjectTracked(obj) {
return trackedObjects.has(obj);
}
let myObject = { id: 123 };
trackObject(myObject);
console.log(isObjectTracked(myObject)); // Natija: true
myObject = null;
// Axlat yig'ilgandan so'ng, isObjectTracked(myObject) 'false' qaytarishi mumkin.
Umumiy Mulohazalar va Eng Yaxshi Amaliyotlar
WeakMap va WeakSet bilan ishlaganda, ushbu umumiy eng yaxshi amaliyotlarni hisobga oling:
- Axlat Yig'ishni Tushunish: Axlat yig'ish deterministik emas. Obyekt qachon axlat yig'uvchi tomonidan tozalanishini aniq bashorat qila olmaysiz. Shuning uchun, obyektga havola yo'qolganda yozuvlarni darhol o'chirish uchun
WeakMapyokiWeakSetga tayana olmaysiz. - Haddan Tashqari Foydalanishdan Saqlaning:
WeakMapvaWeakSetxotirani boshqarish uchun foydali bo'lsa-da, ularni haddan tashqari ishlatmang. Ko'p hollarda, standartMapvaSetmukammal darajada mos keladi va ko'proq moslashuvchanlikni taklif qiladi.WeakMapvaWeakSetdan xotira sizib chiqishini oldini olish uchun kuchsiz havolalar maxsus kerak bo'lganda foydalaning. - Kuchsiz Havolalar uchun Foydalanish Holatlari: Kalit (
WeakMapuchun) yoki qiymat (WeakSetuchun) sifatida saqlayotgan obyektingizning hayot davomiyligi haqida o'ylang. Agar obyekt boshqa obyektning hayot sikliga bog'liq bo'lsa, xotira sizib chiqishining oldini olish uchunWeakMapyokiWeakSetdan foydalaning. - Sinovdagi Qiyinchiliklar: Axlat yig'ishga tayanadigan kodni sinovdan o'tkazish qiyin bo'lishi mumkin. JavaScript'da axlat yig'ishni majburlay olmaysiz. Sinov paytida axlat yig'ishni rag'batlantirish uchun ko'p sonli obyektlarni yaratish va yo'q qilish kabi usullardan foydalanishni ko'rib chiqing.
- Polifillar: Agar
WeakMapvaWeakSetni tabiiy ravishda qo'llab-quvvatlamaydigan eski brauzerlarni qo'llab-quvvatlashingiz kerak bo'lsa, polifillardan foydalanishingiz mumkin. Biroq, polifillar kuchsiz havola xatti-harakatini to'liq takrorlay olmasligi mumkin, shuning uchun sinchkovlik bilan sinovdan o'tkazing.
Misol: Xalqarolashtirish (i18n) Keshi
Xalqarolashtirish (i18n) qo'llab-quvvatlashiga ega veb-ilova yaratayotgan stsenariyni tasavvur qiling. Siz tarjima qilingan satrlarni foydalanuvchining lokaliga asoslanib keshlashtirishni xohlashingiz mumkin. Keshlashni saqlash uchun WeakMapdan foydalanishingiz mumkin, bunda kalit lokal obyekti, qiymat esa o'sha lokal uchun tarjima qilingan satrlar bo'ladi. Lokal endi kerak bo'lmaganda (masalan, foydalanuvchi boshqa tilga o'tganda va eski lokalga endi havola qilinmasa), ushbu lokal uchun kesh avtomatik ravishda axlat yig'uvchi tomonidan tozalanadi.
let i18nCache = new WeakMap();
function getTranslatedStrings(locale) {
if (i18nCache.has(locale)) {
return i18nCache.get(locale);
}
// Serverdan tarjima qilingan satrlarni olishni simulyatsiya qilish.
let translatedStrings = {
"greeting": (locale.language === "fr") ? "Bonjour" : "Hello",
"farewell": (locale.language === "fr") ? "Au revoir" : "Goodbye"
};
i18nCache.set(locale, translatedStrings);
return translatedStrings;
}
let englishLocale = { language: "en", country: "US" };
let frenchLocale = { language: "fr", country: "FR" };
console.log(getTranslatedStrings(englishLocale).greeting); // Natija: Hello
console.log(getTranslatedStrings(frenchLocale).greeting); // Natija: Bonjour
englishLocale = null;
// Axlat yig'ilgandan so'ng, englishLocale uchun yozuv keshdan o'chiriladi.
Bu yondashuv i18n keshining cheksiz o'sishini va ortiqcha xotira iste'mol qilishini oldini oladi, ayniqsa ko'p sonli lokallarni qo'llab-quvvatlaydigan ilovalarda.
Xulosa
WeakMap va WeakSet JavaScript ilovalarida xotirani boshqarish uchun kuchli vositalardir. Ularning cheklovlari va foydalanish holatlarini tushunib, siz xotira sizib chiqishidan holi bo'lgan samaraliroq va mustahkam kod yozishingiz mumkin. Ular har bir stsenariyga mos kelmasligi mumkin bo'lsa-da, obyektlarni axlat yig'uvchi tomonidan tozalanishiga to'sqinlik qilmasdan ma'lumotlarni ular bilan bog'lash kerak bo'lgan holatlarda ular juda muhimdir. JavaScript ilovalaringizni optimallashtirish va foydalanuvchilaringiz qayerda bo'lishidan qat'i nazar, ular uchun yaxshiroq tajriba yaratish uchun ushbu to'plamlardan foydalaning.